package com.szwistar.common.datastruct;

import org.apache.log4j.PropertyConfigurator;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

class KVStoreItem {
	protected long expire = 0; 	// 过期时间(与当前ms相比)，如果=0表示永久有效
	protected Object value;

	public KVStoreItem(Object value, long ttl) {
		this.value = value;
		this.expire = System.currentTimeMillis() + ttl;
	}

	public boolean expired() {
		return System.currentTimeMillis() > expire;
	}
}

/**
 * K-V 内存存储的简单实现
 * @author 张勇
 */
public class KVStore {
	// 实例仓库
	protected static Map<String, KVStore> stores = new ConcurrentHashMap<String, KVStore>();

	/**
	 * 获取一个实例，如果没有，则创建它
	 * @param name 实例名
	 * @return
	 */
	public static KVStore store(String name) {
		KVStore store = stores.get(name);
		if(store == null) {
			store = new KVStore();
			stores.put(name, store);
		}
		return store;
	}

	// K-V 存储
	protected Map<String, KVStoreItem> store = new ConcurrentHashMap<String, KVStoreItem>();

	protected KVStore() {}

	/**
	 * 放入一个持久有效的 K-V 记录
	 * @param key 对象的索引名
	 * @param value 对象
	 * @return
	 */
	public Object put(String key, Object value) {
		return put(key, value, 0);
	}

	/**
	 * 放入一个 K-V 记录
	 * @param key 对象的索引名
	 * @param value 对象
	 * @param ttl 有效期(ms)
	 * @return
	 */
	public Object put(String key, Object value, long ttl) {
		KVStoreItem item = new KVStoreItem(value, ttl);
		item = store.put(key, item);
		return (item == null) ? null : item.value;
	}

	/**
	 * 获取一个存储对象
	 * @param key 对象的索引名
	 * @return 存储对象。如果已经过期，则返回 null。
	 */
	public Object get(String key) {
		if(key == null) { return null; }
		KVStoreItem item = store.get(key);
		if(item == null) { return null; }
		if(item.expired()) { store.remove(key); return null; }
		return item.value;
	}

	/**
	 * 获取某个存储对象的某个属性或字段的值
	 * @param key 对象的索引名
	 * @param prop 属性名(如果是Map的话)/字段名(如果是普通对象的话)
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Object get(String key, String prop) {
		Object obj = get(key);
		if(obj == null) { return null; }

		if(obj instanceof Map) {
			return ((Map<String, Object>)obj).get(prop);
		}

		try {
			return Reflector.getFieldValue(obj, prop);
		} catch(IllegalAccessException e) {
			return null;
		}
	}

	/**
	 * 获取并删除
	 * @param key 索引
	 * @return key 对应的存储对象
	 */
	public Object take(String key) {
		if(key == null) { return null; }
		KVStoreItem item = store.remove(key);
		if(item == null) { return null; }
		return item.value;
	}

	// 测试
	@SuppressWarnings("unused")
	public static void main(String[] args) throws Exception {
		PropertyConfigurator.configure("log4j.properties");

		KVStore.store("smsVerify").put("18612345678", "1234", 15*60*1000);
		Object val = KVStore.store("smsVerify").get("18612345678");
		val = KVStore.store("smsVerify").take("18612345678");
		val = KVStore.store("smsVerify").take("18612345678");
	}
}
